Program Cohen ( Input , Output ) ;

{$I GRAPH.P}

Const
   Up    = 72 ;
   Down  = 80 ;
   Right = 77 ;
   Left  = 75 ;
   Quit  = 113 ;
   Return = 13 ;
Type
   Edges = Record
               x1 , y1 , x2 , y2 : Integer ;
            end ;
   Aray = Array [0..19] of Edges ;

Var
   I , J , x , y , Px , Py , Pc , Code , Wx1 , Wy1 , Wx2 , Wy2 : Integer ;
   Ch : Char ;
   Edge : Aray ;

Procedure Clip ( Wx1 , Wy1 , Wx2 , Wy2  : Integer ; Var E : Edges ) ;
Type
    Outcode = ( l , r , t , b ) ;
    Outset = Set of Outcode ;
Var
    x , y : Integer ;
    P , First , Second : Outset ;
    Done : Boolean ;

Procedure Codes ( x , y : Integer ; Var Gen : Outset ) ;
begin
    Gen := [] ;
    If ( x < Wx1 ) then Gen := Gen + [l] ;
    If ( x > Wx2 ) then Gen := Gen + [r] ;
    If ( y < Wy1 ) then Gen := Gen + [t] ;
    If ( y > Wy2 ) then Gen := Gen + [b] ;
end ;

begin

   Codes ( E.x1 , E.y1 , First ) ;
   Codes ( E.x2 , E.y2 , Second ) ;
   Done := False ;

   While ( ( ( First <> [] ) or ( Second <> [] ) ) and ( Not Done ) )
   begin
      If ( First * Second ) <> [] then Done := True
      else
      begin
         P := First ;
         If ( P = [] ) then
            P := Second ;
         If ( l In P ) then
         begin
            y := Round ( ( Wx1 - E.x1 ) * ( E.y2 - E.y1 ) / ( E.x2 - E.x1 ) + E.y1 ) ;
            x := Wx1 ;
         end ;
         If ( r In P ) then
         begin
            y := Round ( ( Wx2 - E.x1 ) * ( E.y2 - E.y1 ) / ( E.x2 - E.x1 ) + E.y1 ) ;
            x := Wx2 ;
         end ;
         If ( t In P ) then
         begin
            x := Round ( ( Wy1 - E.y1 ) * ( E.x2 - E.x1 ) / ( E.y2 - E.y1 ) + E.x1 ) ;
            y := Wy1 ;
         end ;
         If ( b In P ) then
         begin
            x := Round ( ( Wy2 - E.y1 ) * ( E.x2 - E.x1 ) / ( E.y2 - E.y1 ) + E.x1 ) ;
            y := Wy2 ;
         end ;

         If ( P = First ) then
         begin
            E.x1 := x ;
            E.y1 := y ;
            Codes ( E.x1 , E.y1 , First ) ;
         end
         else
         begin
            E.x2 := x ;
            E.y2 := y ;
            Codes ( E.x2 , E.y2 , Second ) ;
         end ;
      end ;
   end ;
   If ( Not Done ) then
      Draw ( E.x1 , E.y1 , E.x2 , E.y2 , 3 ) ;
end ;

Begin
   GraphMode ;

   Wx1 := 50 ;
   Wy1 := 50 ;
   Wx2 := 150 ;
   Wy2 := 150 ;

   Draw ( Wx1 , Wy1 , Wx2 , Wy1 , 3 ) ;
   Draw ( Wx2 , Wy1 , Wx2 , Wy2 , 3 ) ;
   Draw ( Wx2 , Wy2 , Wx1 , Wy2 , 3 ) ;
   Draw ( Wx1 , Wy2 , Wx1 , Wy1 , 3 ) ;

   I := -1 ;
   x := 160 ;
   y := 100 ;
   Pc := Getdotcolor ( x , y ) ;
   Plot ( x , y , 3 ) ;


   Read ( Kbd , Ch ) ;
   If ( Ch = #27 ) then
      Read ( Kbd , Ch ) ;
   Code := Ord ( Ch ) ;

   While ( Code <> Quit ) do
   begin

      Px := x ;
      Py := y ;

      Case ( Code ) of

          Left : If ( x > 0 ) then
                    x := x - 1 ;
         Right : If ( x < 319 ) then
                    x := x + 1 ;
            Up : If ( y > 0 ) then
                    y := y - 1 ;
          Down : If ( y < 199 ) then
                    y := y + 1 ;
        Return : begin
                    I := I + 1 ;
                    Edge [I].x1 := x ;
                    Edge [I].y1 := y ;
                    Pc := 3 ;
                 end ;
      end ;

      Plot ( Px , Py , Pc ) ;
      Pc := Getdotcolor ( x , y ) ;
      Plot ( x , y , 3 ) ;

      Read ( Kbd , Ch ) ;
      If ( Ch = #27 ) then
         Read ( Kbd , Ch ) ;
      Code := Ord ( Ch ) ;

   end ;


   For J := 0 to I-1 do
   begin
      Edge [J].x2 := Edge [J+1].x1 ;
      Edge [J].y2 := Edge [J+1].y1 ;
   end ;
   Edge [I].x2 := Edge [0].x1 ;
   Edge [I].y2 := Edge [0].y1 ;

   For J := 0 to I do
      Draw ( Edge [J].x1 , Edge [J].y1 , Edge [J].x2 , Edge [J].y2 , 3 ) ;

   Repeat Until Keypressed ;

   Clearscreen ;

   Draw ( Wx1 , Wy1 , Wx2 , Wy1 , 3 ) ;
   Draw ( Wx2 , Wy1 , Wx2 , Wy2 , 3 ) ;
   Draw ( Wx2 , Wy2 , Wx1 , Wy2 , 3 ) ;
   Draw ( Wx1 , Wy2 , Wx1 , Wy1 , 3 ) ;

   For J := 0 to I do
      Clip ( Wx1 , Wy1 , Wx2 , Wy2 , Edge [J] ) ;

   Read ;
   TextMode ;
end.
